package com.jrelax.third.fs.rmi;

import com.jrelax.kit.Md5Kit;
import com.jrelax.third.fs.IRemoteFS;
import com.jrelax.third.fs.Run;
import com.jrelax.third.fs.io.IOHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.text.SimpleDateFormat;
import java.util.*;

public class RemoteFSImpl extends UnicastRemoteObject implements IRemoteFS {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    private String ROOT = "";
    /**
     *
     */
    private static final long serialVersionUID = -5012286024758668527L;

    public RemoteFSImpl() throws RemoteException {
        String path = Run.class.getResource("/").getPath() + "/config.properties";
        File file = new File(path);
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
            Properties prop = new Properties();
            prop.load(fis);

            ROOT = IOHelper.resolvePath(prop.getProperty("rmi.root"));
            File f = new File(ROOT);
            if (!f.exists())
                f.mkdirs();
            logger.info("存储位置：" + f.getPath());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fis != null)
                    fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    @Override
    public String upload(String app, String filename, byte[] stream) throws RemoteException {
        logger.info("上传文件: " + filename);
        //创建保存路径
        String dir = "/" + app + "/file/" + new SimpleDateFormat("yyMMdd").format(new Date()) + "/";
        File fDir = new File(ROOT + dir);
        if (!fDir.exists())
            fDir.mkdirs();

        String tempDir = ROOT + dir + "/$temp$/";
        File fTempDir = new File(tempDir);
        if (!fTempDir.exists())
            fTempDir.mkdirs();

        //将文件保存到临时目录中
        String tempFilePath = tempDir + filename;
        File tempFile = new File(tempFilePath);

        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(tempFile);
            fos.write(stream);
            fos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fos != null)
                    fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        //文件重命名（文件MD5值）
        try {
            String hash = Md5Kit.file_short_8(tempFile);
            String ext = "";
            if (tempFile.getName().indexOf(".") > 0)
                ext = tempFile.getName().substring(tempFile.getName().lastIndexOf("."));
            String filepath = ROOT + dir + hash + ext;
            File destFile = new File(filepath);
            if (destFile.exists())//自动覆盖
                destFile.delete();

            tempFile.renameTo(destFile);
            Map<String, String> result = new HashMap<>();
            result.put("src", filename);
            result.put("dest", dir + hash + ext);
            result.put("app", app);
            result.put("size", stream.length + "");
            logger.info("上传成功: "+result);
            return dir + hash + ext;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    @Override
    public String upload(String app, String dir, String filename, byte[] stream) throws RemoteException {
        //创建保存路径
        if (!dir.startsWith("/")) dir = "/" + dir;
        if (!dir.endsWith("/")) dir = dir + "/";
        dir = "/" + app + dir;
        File fDir = new File(ROOT + dir);
        if (!fDir.exists())
            fDir.mkdirs();

        //将文件保存到临时目录中
        String tempFilePath = ROOT + dir + filename;
        File tempFile = new File(tempFilePath);

        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(tempFile);
            fos.write(stream);
            fos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fos != null)
                    fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return dir + filename;
    }

    /**
     * 创建文件夹
     *
     * @param app
     * @param dir
     * @return
     */
    public int mkdir(String app, String dir) throws RemoteException {
        if (!dir.startsWith("/")) dir = "/" + dir;
        String path = ROOT + "/" + app + dir;
        File file = new File(path);
        if (file.exists()) return TAG_EXISTS;
        file.mkdirs();
        return TAG_SUCCESS;
    }

    public int delete(String app, String filepath) throws RemoteException {
        if (!filepath.startsWith("/")) filepath = "/" + filepath;
        filepath = ROOT + "/" + app + filepath;
        File file = new File(filepath);
        if (file.exists()) {
            file.delete();
        } else {
            return TAG_NOT_EXISTS;
        }
        return TAG_SUCCESS;
    }

    public int deleteDir(String app, String dir, boolean clearAll) throws RemoteException {
        if (!dir.startsWith("/")) dir = "/" + dir;
        String path = ROOT + "/" + app + dir;
        File file = new File(path);
        if (!file.exists()) return TAG_NOT_EXISTS; //判断是否存在
        if (!file.isDirectory()) return TAG_NOT_DIR; //判断是否是文件夹
        if (file.list().length > 0 && !clearAll) return TAG_DIR_NOT_EMPTY;//判断文件夹下是否为空
        file.delete();
        return TAG_SUCCESS;
    }

    @Override
    public byte[] download(String app, String filepath) throws RemoteException {
        if (!filepath.startsWith("/")) filepath = "/" + filepath;
        filepath = ROOT + "/" + app + filepath;
        File file = new File(filepath);
        if (file.exists()) {
            if (file.length() > Integer.MAX_VALUE) {
                System.out.println("文件过大，不支持下载！");
                return null;
            }
            FileInputStream fis = null;
            try {
                fis = new FileInputStream(file);
                byte[] buffer = new byte[(int) file.length()];
                int offset = 0;
                int numRead = 0;
                while (offset < buffer.length
                        && (numRead = fis.read(buffer, offset, buffer.length - offset)) >= 0) {
                    offset += numRead;
                }
                // 确保所有数据均被读取
                if (offset != buffer.length) {
                    throw new IOException("Could not completely read file " + file.getName());
                }
                return buffer;
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }

        } else {
            return null;
        }
        return null;
    }

    @Override
    public List<String> list(String app, String dir) throws RemoteException {
        List<String> fileList = new ArrayList<>();
        if (!dir.startsWith("/")) dir = "/" + dir;
        File fDir = new File(ROOT + "/" + app + dir);
        System.out.println(ROOT + app + dir);
        File[] files = fDir.listFiles();
        if (files != null && files.length > 0) {
            for (File f : files) {
                fileList.add(f.getName());
            }
        }
        return fileList;
    }

    @Override
    public List<String> search(String app, String key) throws RemoteException {
        List<String> list = new ArrayList<>();

        return list;
    }
}
